#include "AdminInterpreter.h"
#include "AdminSerializer.h"
#include "AdminRightManager.h"

AgoraAdmin::AdminInterpreter::AdminInterpreter(IChannelManager *ch, /*IRightManager *rt,*/ IUserManager *us) :
_callbackOk(false),
_channelManager(ch),
_userManager(us)
{
	this->_adminFunctions[GETALLCHANNEL] = &AdminInterpreter::GetAllChannel;
	this->_adminFunctions[CREATECHANNEL] = &AdminInterpreter::CreateChannel;
	this->_adminFunctions[GETALLUSER] = &AdminInterpreter::GetAllUser;
	this->_adminFunctions[JOINCHANNEL] = &AdminInterpreter::JoinChannel;
	this->_adminFunctions[GETHOSTRIGHT] = &AdminInterpreter::GetHostRight;
	this->_adminFunctions[GETCHANNELRIGHT] = &AdminInterpreter::GetChannelRight;
	this->_adminFunctions[DELETECHANNEL] = &AdminInterpreter::DeleteChannel;
	this->_adminFunctions[CREATEUSER] = &AdminInterpreter::CreateUser;
	this->_adminFunctions[DELETEUSER] = &AdminInterpreter::DeleteUser;
	this->_adminFunctions[KICKUSER] = &AdminInterpreter::KickUser;
	this->_adminFunctions[BANUSER] = &AdminInterpreter::BanUser;
	this->_adminFunctions[UNBANUSER] = &AdminInterpreter::UnBanUser;
	this->_adminFunctions[GETBANUSERLIST] = &AdminInterpreter::GetBanUserList;
	this->_adminFunctions[GETBANUSERLISTSERVER] = &AdminInterpreter::GetBanUserListServer;
	this->_adminFunctions[EDITUSERCHANNELRIGHT] = &AdminInterpreter::EditUserChannelRight;
	this->_adminFunctions[EDITUSERHOSTRIGHT] = &AdminInterpreter::EditUserHostRight;
	this->_adminFunctions[CHANGEUSERLOGIN] = &AdminInterpreter::ChangeUserLogin;
	this->_adminFunctions[CHANGEUSERPASSWORD] = &AdminInterpreter::ChangeUserPassword;
	this->_adminFunctions[GETUSERCHANNELRIGHT] = &AdminInterpreter::GetUserChannelRight;
	this->_adminFunctions[GETUSERHOSTRIGHT] = &AdminInterpreter::GetUserHostRight;
	this->_adminFunctions[EDITCHANNEL] = &AdminInterpreter::EditChannel;
	this->_adminFunctions[KICKUSERSERVER] = &AdminInterpreter::KickUserServer;
	this->_adminFunctions[SENDMESSAGE] = &AdminInterpreter::SendMessage;
	this->_adminFunctions[BANUSERSERVER] = &AdminInterpreter::BanUserServer;
	this->_adminFunctions[UNBANUSERSERVER] = &AdminInterpreter::UnBanUserServer;
}

void	AgoraAdmin::AdminInterpreter::SubscribeForcedDisconnectionUser(Callback fct, void *data)
{
	this->_callback = fct;
	this->_callbackData = data;
	this->_callbackOk = true;
}
		

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::Launch(IUser* user, AdminFunction function, void *argument)
{
	return (this->*_adminFunctions[function])(user, argument);;
}

void	AgoraAdmin::AdminInterpreter::SetError(unsigned int code, const std::string& message, ReturnInfo* res)
{
	res->_size = sizeof(int) + message.length() + 1;
	char*	data = new char[res->_size];
	char*	ptr = data;

	memcpy(ptr, &code, sizeof(int));
	ptr += sizeof(int);

	memcpy(ptr, message.c_str(), message.length() + 1);

	res->_informations = data;
	res->_function = TREATERROR;
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetAllChannel(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	res->_function = GETALLCHANNEL;
	res->_informations = AdminSerializer::SerializeChannelList(this->_channelManager->GetChannelList(), res->_size);
	//AdminSerializer::UnserializeChannelList((char*)res->_informations, res->_size);
	res->_userConcerned.push_back(user);

	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::CreateChannel(IUser* user, void* data)
{
	unsigned int size;
	ReturnInfo* res = new ReturnInfo();

	AgoraAdmin::AdminSerializer::ChannelInfo* info = AgoraAdmin::AdminSerializer::UnserializeChannelInfo((char*)data, size);
	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanCreateChannel() || !AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, this->_channelManager->GetChannel(info->idParent)).GetCanCreateChannelChild())
	{
		this->SetError(ERRORNORIGHTCREATECHANNEL, "Insufficiant right to create channel", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	if (this->_channelManager->ChannelExists(info->idParent, info->name))
	{
		// TODO define message
		this->SetError(ERRORCHANNELEXISTS, "Channel already exists", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	res->_function = CREATECHANNEL;
	AgoraAdmin::IChannel*	channel = this->_channelManager->CreateChannel(this->_channelManager->GetChannel(info->idParent), info->name, info->maxNameLength, info->password, info->maxPasswordLength, info->motd, info->maxMotdLength, info->description, info->maxDescriptionLength, info->visible, info->maxUser, info->maxTalker);
	
	std::map<unsigned int, AgoraAdmin::IChannel*> mapChannel;
	mapChannel[0] = channel;
	res->_informations = AgoraAdmin::AdminSerializer::SerializeChannelList(mapChannel, res->_size);
	if (info->visible)
		this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>		AgoraAdmin::AdminInterpreter::JoinChannel(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();
	std::string password((char*)data + sizeof(int));

	IChannel* chan = this->_channelManager->GetChannel(*((int*)data));

	if (!chan)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (chan->UserIsBan(user->GetId()))
	{
		this->SetError(ERRORUSERCHANNELBAN, "User is banned from channel", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (chan->GetPassword() != password)
	{
		this->SetError(ERRORCHANNELPASSWORD, "Channel password incorrect", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	if (!this->_channelManager->MoveUser(user->GetCurrentChannelId(), *((int*)data), user))
	{
		// TODO define
		this->SetError(ERRORNOCHANNEL, "Unable to join this channel", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	// pas top, ok pour demo, ne permet de joindre un channel a la connec qui soit autre que chanroot
	// mais on peut toujours changer de chan a partir du root
	if (user->GetCurrentChannelId() != 0 && !AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanChangeChannel())
	{
		this->SetError(ERRORNORIGHTCHANGECHANNEL, "Insufficiant right to change channel", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	res->_function = JOINCHANNEL;
	int*	data2 = new int[2];
	data2[0] = user->GetId();
	data2[1] = user->GetCurrentChannelId();
	res->_informations = data2;
	res->_size = sizeof(int) * 2;
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetAllUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	res->_function = GETALLUSER;
	res->_informations = AdminSerializer::SerializeUserList(*(this->_userManager->GetUser()), res->_size);
	//AdminSerializer::UnserializeChannelList((char*)res->_informations, res->_size);
	res->_userConcerned.push_back(user);

	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetHostRight(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	res->_function = GETHOSTRIGHT;
	res->_informations = AdminSerializer::SerializeHostRight(&RightManager::GetRightManager()->GetHostRight(user), res->_size);
	res->_userConcerned.push_back(user);

	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetChannelRight(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	unsigned int idChannel = *((int*)data);
	IChannel*	channel = this->_channelManager->GetChannel(idChannel);
	if (channel)
	{
		res->_function = GETCHANNELRIGHT;
		char*	tmp = (char*)AdminSerializer::SerializeChannelRight(&RightManager::GetRightManager()->GetChannelRight(user, channel), res->_size);
		char*	data = new char[sizeof(int) + res->_size];
		memcpy(data, &idChannel, sizeof(int));
		memcpy(data + sizeof(int), tmp, res->_size);
		res->_informations = data;
		res->_size += sizeof(int);
		delete tmp;
	}
	else
		this->SetError(ERRORNOCHANNEL, "Channel is not valid", res);
	res->_userConcerned.push_back(user);

	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::DeleteChannel(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();
	std::stack<IUser*> usrToMove;

	unsigned int idChannel = *((int*)data);
	IChannel*	channel = this->_channelManager->GetChannel(idChannel);
	if (channel)
	{
		if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanDeleteChannel() || !AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, this->_channelManager->GetChannel(channel->GetId())).GetCanDeleteChannelChild())
		{
			this->SetError(ERRORNORIGHTDELETECHANNEL, "Insufficiant right to delete channel", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}

		AgoraAdmin::RightManager::GetRightManager()->RemoveChannelRight(channel);
		char*	data = new char[sizeof(int)];
		unsigned int idChannel = channel->GetId();
		memcpy(data, &idChannel, sizeof(int));
		res->_informations = data;
		this->_channelManager->DeleteChannel(channel, usrToMove);
		res->_function = DELETECHANNEL;
		res->_size = sizeof(int);
		this->FillUserConcerned(res);
	}
	else
	{
		this->SetError(ERRORNOCHANNEL, "Channel is not valid", res);
		res->_userConcerned.push_back(user);
	}

	std::stack<ReturnInfo*> stk = this->CreateStackFromOneRes(res);
	while (!usrToMove.empty())
	{
		ReturnInfo* resJ = new ReturnInfo();
		resJ->_function = JOINCHANNEL;
		int*	data2 = new int[2];
		IUser*	usrJ = usrToMove.top();
		data2[0] = usrJ->GetId();
		data2[1] = usrJ->GetCurrentChannelId();
		resJ->_informations = data2;
		resJ->_size = sizeof(int) * 2;
		this->FillUserConcerned(resJ);
		usrToMove.pop();
		stk.push(resJ);
	}
	return stk;
}


AgoraAdmin::AdminInterpreter::ReturnInfo*			AgoraAdmin::AdminInterpreter::ConnectUser(IUser* user)
{
	ReturnInfo* res = new ReturnInfo();
	std::map<unsigned int, IUser*> mapUsers;

	mapUsers[user->GetId()] = user;
	res->_informations = AgoraAdmin::AdminSerializer::SerializeUserList(mapUsers, res->_size);
	res->_function = CONNECT;

	this->FillUserConcerned(res);
	return res;
}

AgoraAdmin::AdminInterpreter::ReturnInfo*			AgoraAdmin::AdminInterpreter::DisconnectUser(IUser* user)
{
	ReturnInfo* res = new ReturnInfo();
	res->_function = DISCONNECT;

	unsigned int *data = new unsigned int[1];
	data[0] = user->GetId();
	res->_informations = data;
	res->_size = sizeof(unsigned int);

	this->FillUserConcerned(res);
	return res;
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::CreateUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	std::string	login((char*)data);
	std::string	pass((char*)data + login.length() + 1);
	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to create user", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	if (this->_userManager->UserExists(login))
	{
		// TODO define message
		this->SetError(ERRORUSEREXISTS, "User already exists", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	res->_function = CREATEUSER;
	AgoraAdmin::IUser*	newuser = this->_userManager->CreateUser(login, pass);
	std::map<unsigned int, AgoraAdmin::IUser*> mapIUser;
	mapIUser[0] = newuser;
	res->_informations = AgoraAdmin::AdminSerializer::SerializeUserList(mapIUser, res->_size);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>		AgoraAdmin::AdminInterpreter::DeleteUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to delete user", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	IUser*	usrDel = this->_userManager->GetUser(*(int*)data);
	
	if (!usrDel)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (usrDel->IsConnected())
	{
		this->_callback(usrDel, this->_callbackData);
	//	this->_channelManager->GetChannel(user->GetCurrentChannelId())->RemoveUser(usrDel);
	}
	AgoraAdmin::RightManager::GetRightManager()->RemoveHostRight(usrDel);
	AgoraAdmin::RightManager::GetRightManager()->RemoveChannelRight(usrDel);
	this->_userManager->DeleteUser(*(int*)data);
	unsigned int	*data2 = new unsigned int[1];
	data2[0] = *(int*)data;
	res->_informations = data2;
	res->_function = DELETEUSER;
	res->_size = sizeof(unsigned int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::KickUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrKick = this->_userManager->GetUser(*(int*)data);
	
	if (!usrKick)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}


	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
	if (!fromChn)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanKickUser())
	{
		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanKickUser() && usrKick->GetCurrentChannelId() == user->GetCurrentChannelId())
		{
			this->SetError(ERRORNORIGHTKICKUSER, "Insufficiant right to kick user from channel", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
	}
	
	/*move from channel id to channel root*/
	if (!this->_channelManager->MoveUser(fromChn->GetId(), 0, usrKick))
	{
		this->SetError(ERRORMOVEUSER, "Error while moving user", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	char*	data2 = new char[sizeof(int) * 2];
	//unsigned int idUsr = usrKick->GetId();
	memcpy(data2, data, sizeof(int) * 2);
	res->_informations = data2;
	res->_function = KICKUSER;
	res->_size = sizeof(int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::BanUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrBan = this->_userManager->GetUser(*(int*)data);
	
	if (!usrBan)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}


	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
	if (!fromChn)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanBanUser())
	{
		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanBanUser() && usrBan->GetCurrentChannelId() == user->GetCurrentChannelId())
		{
			this->SetError(ERRORNORIGHTBANUSER, "Insufficiant right to ban user from channel", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
	}
	
	if (usrBan->IsConnected())
	{
		/*move from channel id to channel root*/
		if (!this->_channelManager->MoveUser(fromChn->GetId(), 0, usrBan))
		{
			this->SetError(ERRORMOVEUSER, "Error while moving user", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
	}

	fromChn->AddBanList(usrBan->GetId());

	char*	data2 = new char[sizeof(int) * 2];
	//unsigned int idUsr = usrBan->GetId();
	memcpy(data2, data, sizeof(int) * 2);
	res->_informations = data2;
	res->_function = BANUSER;
	res->_size = 2 * sizeof(int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetBanUserList(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data));
	if (!fromChn)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	std::map<unsigned int, IUser*>	lst;
	std::list<unsigned int>::iterator	iteCur = fromChn->GetBanList().begin();
	std::list<unsigned int>::iterator	iteEnd = fromChn->GetBanList().end();
	while (iteCur != iteEnd)
	{
		IUser* u = this->_userManager->GetUser(*iteCur);
		lst[u->GetId()] = u;
		iteCur++;
	}
	char* dataSeri = reinterpret_cast<char*>(AdminSerializer::SerializeUserList(lst, res->_size));
	char*	data2 = new char[sizeof(int) + res->_size];
	memcpy(data2, data, sizeof(int));
	memcpy(data2 + sizeof(int), dataSeri, res->_size);
	delete dataSeri;
	res->_informations = data2;
	res->_size += sizeof(int);
	res->_function = GETBANUSERLIST;
	res->_userConcerned.push_back(user);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::UnBanUser(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrUnBan = this->_userManager->GetUser(*(int*)data);
	
	if (!usrUnBan)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}


	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
	if (!fromChn)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanBanUser() && fromChn->GetId() == user->GetCurrentChannelId())
		{
			this->SetError(ERRORNORIGHTBANUSER, "Insufficiant right to unban user from channel", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
	}
	
	fromChn->RemoveBanList(usrUnBan->GetId());

	char*	data2 = new char[sizeof(int) * 2];
	//unsigned int idUsr = usrUnBan->GetId();
	memcpy(data2, data, sizeof(int) * 2);
	res->_informations = data2;
	res->_function = UNBANUSER;
	res->_size = sizeof(int) * 2;
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::EditUserChannelRight(IUser* user, void* data)
{
	unsigned int	size;
	ReturnInfo*		res = new ReturnInfo();

	IUser* usrEdit = this->_userManager->GetUser(*(int*)data);
	
	if (!usrEdit)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
	if (!fromChn)
	{
		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanEditUserRight() && usrEdit->GetCurrentChannelId() == user->GetCurrentChannelId())
		{
			this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to edit user rights", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
	}

	AgoraAdmin::AdminSerializer::ChannelRightInfo* info = AgoraAdmin::AdminSerializer::UnserializeChannelRight((char*)data + sizeof(int) * 2, size);
	AgoraAdmin::RightManager::GetRightManager()->SetChannelRight(usrEdit, fromChn, info->canCreate, info->canDelete, info->canEdit, info->canEditUser, info->canTalk, info->canWrite, info->canKick, info->canBan);
	res->_function = EDITUSERCHANNELRIGHT;
	res->_size = 2 * sizeof(int) + size;
	char*	data2 = new char[res->_size];
	memcpy(data2, data, res->_size);
	res->_informations = data2;
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::EditUserHostRight(IUser* user, void* data)
{
	unsigned int	size;
	ReturnInfo*		res = new ReturnInfo();

	IUser* usrEdit = this->_userManager->GetUser(*(int*)data);
	
	if (!usrEdit)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to edit user rights", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	AgoraAdmin::AdminSerializer::HostRightInfo* info = AgoraAdmin::AdminSerializer::UnserializeHostRight((char*)data + sizeof(int), size);
	AgoraAdmin::RightManager::GetRightManager()->SetHostRight(usrEdit, info->canChangeLogin, info->canChangePassword, info->canChangeChannel, info->canCreateChannel, info->canDeleteChannel, info->canMoveChannel, info->canKickUser, info->canBanUser, info->canEditUser);
	res->_function = EDITUSERHOSTRIGHT;
	res->_size = sizeof(int) + size;
	char*	data2 = new char[res->_size];
	memcpy(data2, data, res->_size);
	res->_informations = data2;
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::ChangeUserLogin(IUser* user, void* data)
{
	ReturnInfo*		res = new ReturnInfo();

	IUser* usrEdit = this->_userManager->GetUser(*(int*)data);
	
	if (!usrEdit)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (usrEdit != user && !AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to edit user informations", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (usrEdit == user && !AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanChangeLogin())
	{
		this->SetError(ERRORNORIGHTCHANGELOGIN, "Insufficiant right to change login", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	std::string	login((char*)data + sizeof(int));
	usrEdit->SetLogin(login);
	char*	data2 = new char[sizeof(int) + login.length() + 1];
	unsigned int	id = usrEdit->GetId();
	memcpy(data2, &id, sizeof(int));
#ifdef _WIN32
	strncpy_s(data2 + sizeof(int), sizeof(int) + login.length() + 1, login.c_str(), login.length());
#else
	strncpy(data2 + sizeof(int), login.c_str(), login.length());
#endif
	res->_informations = data2;
	res->_function = CHANGEUSERLOGIN;
	res->_size = sizeof(int) + login.length() + 1;
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::ChangeUserPassword(IUser* user, void* data)
{
	ReturnInfo*		res = new ReturnInfo();

	IUser* usrEdit = this->_userManager->GetUser(*(int*)data);
	
	if (!usrEdit)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (usrEdit != user && !AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTEDITUSER, "Insufficiant right to edit user informations", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (usrEdit == user && !AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanChangePassword())
	{
		this->SetError(ERRORNORIGHTCHANGEPASSWORD, "Insufficiant right to change password", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	std::string	password((char*)data + sizeof(int));
	usrEdit->SetPassword(password);
	char*	data2 = new char[sizeof(int) + password.length() + 1];
	unsigned int	id = usrEdit->GetId();
	memcpy(data2, &id, sizeof(int));
#ifdef _WIN32
	strncpy_s(data2 + sizeof(int), sizeof(int) + password.length() + 1, password.c_str(), password.length());
#else
	strncpy(data2 + sizeof(int), password.c_str(), password.length());
#endif
	res->_informations = data2;
	res->_function = CHANGEUSERPASSWORD;
	res->_size = sizeof(int) + password.length() + 1;
	res->_userConcerned.push_back(usrEdit);
	if (usrEdit != user)
		res->_userConcerned.push_back(user);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetUserChannelRight(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	unsigned int idUser = *(int*)data;
	IUser* usr = this->_userManager->GetUser(idUser);
	if (!usr)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	unsigned int idChannel = *((int*)data + 1);
	IChannel*	channel = this->_channelManager->GetChannel(idChannel);
	if (channel)
	{
		res->_function = GETUSERCHANNELRIGHT;
		char*	tmp = (char*)AdminSerializer::SerializeChannelRight(&RightManager::GetRightManager()->GetChannelRight(usr, channel), res->_size);
		char*	data2 = new char[2 * sizeof(int) + res->_size];
		memcpy(data2, &idUser, sizeof(int));
		memcpy(data2 + sizeof(int), &idChannel, sizeof(int));
		memcpy(data2 + 2 * sizeof(int), tmp, res->_size);
		res->_informations = data2;
		res->_size += 2 * sizeof(int);
		delete tmp;
	}
	else
		this->SetError(ERRORNOCHANNEL, "Channel is not valid", res);
	res->_userConcerned.push_back(user);

	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetUserHostRight(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	unsigned int idUser = *(int*)data;
	IUser* usr = this->_userManager->GetUser(idUser);
	if (!usr)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	res->_function = GETUSERHOSTRIGHT;
	char*	tmp = (char*)AdminSerializer::SerializeHostRight(&RightManager::GetRightManager()->GetHostRight(usr), res->_size);
	char*	data2 = new char[sizeof(int) + res->_size];
	memcpy(data2, &idUser, sizeof(int));
	memcpy(data2 + sizeof(int), tmp, res->_size);
	res->_informations = data2;
	res->_size += sizeof(int);
	delete tmp;
	res->_userConcerned.push_back(user);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::EditChannel(IUser* user, void* data)
{
	unsigned int	size;
	ReturnInfo* res = new ReturnInfo();

	IChannel* chan = this->_channelManager->GetChannel(*((int*)data));
	if (!chan)
	{
		this->SetError(ERRORNOCHANNEL, "Channel is not valid", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, chan).GetCanEditChannel())
	{
		this->SetError(ERRORNORIGHTEDITCHANNEL, "Insufficiant right to edit channel", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	AgoraAdmin::AdminSerializer::ChannelInfo* info = AgoraAdmin::AdminSerializer::UnserializeChannelInfo((char*)data + sizeof(int) * 2, size);
	
	if (info->name != chan->GetName() && this->_channelManager->ChannelExists(info->idParent, info->name))
	{
		this->SetError(ERRORCHANNELEXISTS, "Channel already exists", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	chan->SetName(info->name);
	chan->SetMaxNameLength(info->maxNameLength, false);
	int	changePass = *((int*)data + 1);
	if (changePass == 1)
		chan->SetPassword(info->password, false);
	chan->SetMaxPasswordLength(info->maxPasswordLength, false);
	chan->SetMotd(info->motd, false);
	chan->SetMaxMotdLength(info->maxMotdLength, false);
	chan->SetDescription(info->description, false);
	chan->SetMaxDescriptionLength(info->maxDescriptionLength, false);
	chan->SetVisibility(info->visible, false);
	chan->SetMaxUser(info->maxUser, false);
	chan->SetMaxTalker(info->maxTalker, false);

	std::map<unsigned int, AgoraAdmin::IChannel*> mapChannel;
	mapChannel[0] = chan;
	res->_informations = AgoraAdmin::AdminSerializer::SerializeChannelList(mapChannel, res->_size);
	res->_function = EDITCHANNEL;
	if (info->visible)
		this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}


std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::SendMessage(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();
	int	msgType = *((int*)data);
	char* message = (char*)data + sizeof(int) * 2;
	unsigned int msgLen = strlen(message);
	if (msgLen > 1024)
	{
		msgLen = 1024;
		message[msgLen] = 0;
	}

	if (msgType == MSGALLCHANNEL)
	{
		this->FillUserConcerned(res);
	}
	else if (msgType == MSGCHANNEL)
	{
		IChannel* chan = this->_channelManager->GetChannel(*((int*)data + 1));
		if (!chan)
		{
			this->SetError(ERRORNOCHANNEL, "Channel is not valid", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, chan).GetCanWriteChannel())
		{
			this->SetError(ERRORNORIGHTWRITECHANNEL, "Cannot write in channel", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
		std::list<IUser*>::iterator	iteCurrent = chan->GetUser().begin();
		std::list<IUser*>::iterator	iteEnd = chan->GetUser().end();
		while (iteCurrent != iteEnd)
		{
			res->_userConcerned.push_back(*iteCurrent);
			++iteCurrent;
		}
	}
	else if (msgType == MSGUSER)
	{
		unsigned int idUser = *((int*)data + 1);
		IUser* usr = this->_userManager->GetUser(idUser);
		if (!usr || !usr->IsConnected())
		{
			this->SetError(ERRORNOUSER, "User does not exist", res);
			res->_userConcerned.push_back(user);
			return this->CreateStackFromOneRes(res);
		}
		res->_userConcerned.push_back(usr);
	}
	else
	{
		this->SetError(ERRORMSGTYPE, "Wrong message type", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	
	res->_function = SENDMESSAGE;
	res->_size = sizeof(int) * 3 + msgLen + 1;
	char*	data2 = new char[res->_size];
	unsigned int idFrom = user->GetId();
	memcpy(data2, &idFrom, sizeof(int));
	memcpy(data2 + sizeof(int), data, sizeof(int) * 2);
	memcpy(data2 + sizeof(int) * 3, (char*)data + sizeof(int) * 2, msgLen + 1);
	res->_informations = data2;
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::KickUserServer(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrKick = this->_userManager->GetUser(*(int*)data);
	
	if (!usrKick)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanKickUser())
	{
		this->SetError(ERRORNORIGHTKICKUSER, "Insufficiant right to kick user from server", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	
	char*	data2 = new char[sizeof(int)];
	unsigned int idUsr = usrKick->GetId();
	memcpy(data2, &idUsr, sizeof(int));
	res->_informations = data2;
	res->_function = KICKUSERSERVER;
	res->_size = sizeof(int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::BanUserServer(AgoraAdmin::IUser *user, void *data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrBan = this->_userManager->GetUser(*(int*)data);
	
	if (!usrBan)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanBanUser())
	{
		this->SetError(ERRORNORIGHTBANUSER, "Insufficiant right to ban user from server", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	
	char*	data2 = new char[sizeof(int)];
	unsigned int idUsr = usrBan->GetId();
	memcpy(data2, &idUsr, sizeof(int));
	res->_informations = data2;
	res->_function = BANUSERSERVER;
	res->_size = sizeof(int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::UnBanUserServer(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	IUser* usrUnBan = this->_userManager->GetUser(*(int*)data);
	
	if (!usrUnBan)
	{
		this->SetError(ERRORNOUSER, "User does not exist", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}

	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
	{
		this->SetError(ERRORNORIGHTBANUSER, "Insufficiant right to unban user from server", res);
		res->_userConcerned.push_back(user);
		return this->CreateStackFromOneRes(res);
	}
	
	char*	data2 = new char[sizeof(int)];
	unsigned int idUsr = usrUnBan->GetId();
	memcpy(data2, &idUsr, sizeof(int));
	res->_informations = data2;
	res->_function = UNBANUSERSERVER;
	res->_size = sizeof(int);
	this->FillUserConcerned(res);
	return this->CreateStackFromOneRes(res);
}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetBanUserListServer(IUser* user, void* data)
{
	ReturnInfo* res = new ReturnInfo();

	res->_function = GETBANUSERLISTSERVER;
	res->_userConcerned.push_back(user);
	return this->CreateStackFromOneRes(res);
}

//std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::MuteUser(IUser* user, void* data)
//{
//	ReturnInfo* res = new ReturnInfo();
//
//	IUser* usrMute = this->_userManager->GetUser(*(int*)data);
//	
//	if (!usrMute)
//	{
//		this->SetError(ERRORNOUSER, "User does not exist", res);
//		res->_userConcerned.push_back(user);
//		return this->CreateStackFromOneRes(res);
//	}
//
//	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
//	if (!fromChn)
//	{
//		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
//		res->_userConcerned.push_back(user);
//		return this->CreateStackFromOneRes(res);
//	}
//
//	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
//	{
//		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanEditUserRight() && usrMute->GetCurrentChannelId() == user->GetCurrentChannelId())
//		{
//			this->SetError(ERRORNORIGHTMUTEUSER, "Insufficiant right to mute user in channel", res);
//			res->_userConcerned.push_back(user);
//			return this->CreateStackFromOneRes(res);
//		}
//	}
//	
//	fromChn->AddMuteUser(usrMute);
//
//	char*	data2 = new char[sizeof(int)];
//	unsigned int idUsr = usrMute->GetId();
//	memcpy(data2, &idUsr, sizeof(int));
//	res->_informations = data2;
//	res->_function = MUTEUSER;
//	res->_size = sizeof(int);
//	this->FillUserConcerned(res);
//	return this->CreateStackFromOneRes(res);
//}
//
//std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::GetMuteUserList(IUser* user, void* data)
//{
//	ReturnInfo* res = new ReturnInfo();
//
//	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data));
//	if (!fromChn)
//	{
//		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
//		res->_userConcerned.push_back(user);
//		return this->CreateStackFromOneRes(res);
//	}
//
//	/*std::map<unsigned int, IUser*>	lst;
//	std::list<unsigned int>::iterator	iteCur = fromChn->GetBanList().begin();
//	std::list<unsigned int>::iterator	iteEnd = fromChn->GetBanList().end();
//	while (iteCur != iteEnd)
//	{
//		IUser* u = this->_userManager->GetUser(*iteCur);
//		lst[u->GetId()] = u;
//		iteCur++;
//	}*/
//	res->_informations = AdminSerializer::SerializeUserList(fromChn->GetMuteMap(), res->_size);
//	res->_function = GETMUTEUSERLIST;
//	res->_userConcerned.push_back(user);
//	return this->CreateStackFromOneRes(res);
//}
//
//std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*>	AgoraAdmin::AdminInterpreter::UnMuteUser(IUser* user, void* data)
//{
//	ReturnInfo* res = new ReturnInfo();
//
//	IUser* usrUnMute = this->_userManager->GetUser(*(int*)data);
//	
//	if (!usrUnMute)
//	{
//		this->SetError(ERRORNOUSER, "User does not exist", res);
//		res->_userConcerned.push_back(user);
//		return this->CreateStackFromOneRes(res);
//	}
//
//	IChannel* fromChn = this->_channelManager->GetChannel(*((int*)data + 1));
//	if (!fromChn)
//	{
//		this->SetError(ERRORNOCHANNEL, "Channel does not exist", res);
//		res->_userConcerned.push_back(user);
//		return this->CreateStackFromOneRes(res);
//	}
//
//	if (!AgoraAdmin::RightManager::GetRightManager()->GetHostRight(user).GetCanEditUser())
//	{
//		if (!AgoraAdmin::RightManager::GetRightManager()->GetChannelRight(user, fromChn).GetCanBanUser() && fromChn->GetId() == user->GetCurrentChannelId())
//		{
//			this->SetError(ERRORNORIGHTMUTEUSER, "Insufficiant right to unmute user in channel", res);
//			res->_userConcerned.push_back(user);
//			return this->CreateStackFromOneRes(res);
//		}
//	}
//	
//	fromChn->RemoveMuteUser(usrUnMute);
//
//	char*	data2 = new char[sizeof(int)];
//	unsigned int idUsr = usrUnMute->GetId();
//	memcpy(data2, &idUsr, sizeof(int));
//	res->_informations = data2;
//	res->_function = UNMUTEUSER;
//	res->_size = sizeof(int);
//	this->FillUserConcerned(res);
//	return this->CreateStackFromOneRes(res);
//}

std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*> AgoraAdmin::AdminInterpreter::CreateStackFromOneRes(ReturnInfo* res)
{
	std::stack<AgoraAdmin::AdminInterpreter::ReturnInfo*> stc;

	stc.push(res);
	return stc;
}

void	AgoraAdmin::AdminInterpreter::FillUserConcerned(ReturnInfo* res)
{
	std::map<unsigned int, IUser*>* mapUser = this->_userManager->GetUser();
	std::map<unsigned int, IUser*>::iterator	iteCurrent = mapUser->begin();
	std::map<unsigned int, IUser*>::iterator	iteEnd = mapUser->end();
	while (iteCurrent != iteEnd)
	{
		if ((*iteCurrent).second->IsConnected())
			res->_userConcerned.push_back((*iteCurrent).second);
		++iteCurrent;
	}
}
